local TinyGame = {}
local TinyGameItem = require("Module/TinyGame/Widget/TinyGameItem");
local TinyGameLine = require("Module/TinyGame/Widget/TinyGameLine");

function TinyGame:init()
    self.btnMenu = nil;
    self.checkerboard = nil;
    self.lineDic = nil;
    self.lineBox = nil;
    self.items = nil;
    self.itemSelectedDic = nil;
    self.drawLinkItemDic = nil;
end

function TinyGame:onStart()
    self.btnMenu = self:find("btnMenu", CButton);
    Utils.addClick(self.btnMenu, function()
        Dispatcher:dispatch(EventType.TinyGameOver_Open);
    end);
    self:createCheckerboard();
    self:createLineBox();
    self.btnMenu.transform:SetAsLastSibling();
end

function TinyGame:onShow()
    self:initCheckerboard();
    self:addListener(EventType.TinyGameItem_Selected, function(item)
        self:onItemSelected(item);
    end);
    self:addListener(EventType.TinyGame_Again, function()
        self:initCheckerboard();
    end);
end

function TinyGame:onHide()
    
end

function TinyGame:onDestroy()
    -- self.checkerboard:destroy();
    -- TimeMgr:delayFun(2,function ()
    --     for k, v in pairs(self.items) do
    --         print(v.gameObject)
    --         v:destroy();
    --     end
    -- end);
    
    -- for k, v in pairs(self.lineDic) do
    --     v:destroy();
    -- end
end

function TinyGame:onItemSelected(item)
    table.insert(self.itemSelectedDic, item);
    if #self.itemSelectedDic >= 2 then
        if self:isCheckLinked(self.itemSelectedDic[1], self.itemSelectedDic[2]) then
            table.insert(self.drawLinkItemDic, 1, self.itemSelectedDic[1]);
            table.insert(self.drawLinkItemDic, self.itemSelectedDic[2]);
            self:drawLink();
        else
            self.itemSelectedDic[1]:setSelected(false);
            table.remove(self.itemSelectedDic, 1);
        end
    end
end

function TinyGame:createCheckerboard()
    self.checkerboard = ClassUtils:extends({}, Display);
    self.checkerboard:loadPrefab(nil, self.gameObject);
    self.checkerboard.gameObject.name = "checkerboard";
    self.checkerboard.width = TinyGameData.distance * (TinyGameData.horizontalCount - 1);
    self.checkerboard.height = TinyGameData.distance * (TinyGameData.verticalCount - 1);
    Utils.setTfPos(self.checkerboard.gameObject.transform, -self.checkerboard.width / 2, -30 - self.checkerboard.height / 2);
    self.items = {};
    for i = 0, TinyGameData.horizontalCount - 1 do
        for j = 0, TinyGameData.verticalCount - 1 do
            local item = TinyGameItem:new(i, j, self.checkerboard.gameObject);
            local key = i .. "" .. j;
            self.items[key] = item;
        end
    end
end

function TinyGame:createLineBox()
    self.lineBox = ClassUtils:extends({}, Display);
    self.lineBox:loadPrefab(nil, self.gameObject);
    self.lineBox.gameObject.name = "lineBox";
    self.lineDic = {};
    for i = 1, 3 do
        local line = TinyGameLine:new(self.lineBox.gameObject, i);
        table.insert(self.lineDic, line);
    end
end

function TinyGame:initCheckerboard()
    local tempItems = {};
    for _, v in pairs(self.items) do
        local i = v.xIndex;
        local j = v.yIndex;
        v:setEmpty(true);
        v:setSelected(false);
        if i ~= 0 and j ~= 0 and i ~= (TinyGameData.horizontalCount - 1) and j ~= (TinyGameData.verticalCount - 1) then
            table.insert(tempItems, v);
        end
    end
    while #tempItems > 0 do
        local iconName = math.random(TinyGameData.iconAmount);
        for i = 1, 2 do
            local tempIndex = math.random(#tempItems);
            local tempItem = tempItems[tempIndex];
            tempItem:setIcon(iconName);
            tempItem:setEmpty(false);
            table.remove(tempItems, tempIndex);
        end
    end
    for i, v in ipairs(self.lineDic) do
        v:setVisible(false);
    end
    self.itemSelectedDic = {};
    self.drawLinkItemDic = {};
    self:autoFinishGame();
    self.drawLinkItemDic = {};
end

function TinyGame:isCheckLinked(item1, item2)
    if item1.iconName ~= item2.iconName then
        return false;
    end
    if self:lineLinkOne(item1, item2) then
        return true;
    elseif self:lineLinkTwo(item1, item2) then
        return true;
    elseif self:lineLinkThree(item1, item2) then
        return true;
    end
    return false;
end

function TinyGame:lineLinkOne(p1, p2)
    --（1）0转角连通（直线连通）：两个图片的纵坐标或横坐标相等，且两者连线间没有其他图案阻隔。
    if p1.xIndex == p2.xIndex or p1.yIndex == p2.yIndex then
        if (math.abs(p1.xIndex - p2.xIndex) + math.abs(p1.yIndex - p2.yIndex) <= 1) then
            return true;
        end
        if p1.xIndex == p2.xIndex then
            local yOffset = math.abs(p1.yIndex - p2.yIndex);
            local min = p1.yIndex < p2.yIndex and p1 or p2;
            for i = 1, yOffset - 1 do
                if self:checkPoint(min.xIndex, min.yIndex + i) == false then
                    return false;
                end
            end
            return true;
        end
        if p1.yIndex == p2.yIndex then
            local xOffset = math.abs(p1.xIndex - p2.xIndex);
            local min = p1.xIndex < p2.xIndex and p1 or p2;
            for i = 1, xOffset - 1 do
                if self:checkPoint(min.xIndex + i, min.yIndex) == false then
                    return false;
                end
            end
            return true;
        end
    else
        return false;
    end
end

function TinyGame:lineLinkTwo(p1, p2)
    --（2）1转角连通（2直线连通）：两个图片的纵坐标和横坐标都不相等。
    if p1.xIndex == p2.xIndex or p1.yIndex == p2.yIndex then
        return false;
    end
    local p3 = self.items[p2.xIndex .. "" .. p1.yIndex];
    if self:checkPoint(p3.xIndex, p3.yIndex) and self:lineLinkOne(p1, p3) and self:lineLinkOne(p2, p3) then
        table.insert(self.drawLinkItemDic, p3);
        return true;
    end
    local p4 = self.items[p1.xIndex .. "" .. p2.yIndex];
    if self:checkPoint(p4.xIndex, p4.yIndex) and self:lineLinkOne(p1, p4) and self:lineLinkOne(p2, p4) then
        table.insert(self.drawLinkItemDic, p4);
        return true;
    end
    return false;
end

function TinyGame:lineLinkThree(p1, p2)
    --（3）2转角连通（3直线连通）
    local linkItemDic = {};
    local item = nil;
    for i = p1.xIndex + 1, TinyGameData.horizontalCount - 1 do
        item = self.items[i .. "" .. p1.yIndex];
        if self:checkPoint(item.xIndex, item.yIndex) then
            table.insert(linkItemDic, item);
        else
            break;
        end
    end
    for i = p1.xIndex - 1, 0, -1 do
        item = self.items[i .. "" .. p1.yIndex];
        if self:checkPoint(item.xIndex, item.yIndex) then
            table.insert(linkItemDic, item);
        else
            break;
        end
    end
    for i = p1.yIndex + 1, TinyGameData.verticalCount - 1 do
        item = self.items[p1.xIndex .. "" .. i];
        if self:checkPoint(item.xIndex, item.yIndex) then
            table.insert(linkItemDic, item);
        else
            break;
        end
    end
    for i = p1.yIndex - 1, 0, -1 do
        item = self.items[p1.xIndex .. "" .. i];
        if self:checkPoint(item.xIndex, item.yIndex) then
            table.insert(linkItemDic, item);
        else
            break;
        end
    end
    for i, v in ipairs(linkItemDic) do
        if self:lineLinkTwo(v, p2) then
            table.insert(self.drawLinkItemDic, 1, v);
            return true;
        end
    end
    return false;
end

function TinyGame:checkPoint(xIndex, yIndex)
    local key = xIndex .. "" .. yIndex;
    return self.items[key].isEmpty;
end

function TinyGame:checkGameOver(openGameOver)
    for k, v in pairs(self.items) do
        if not v.isEmpty then
            return false;
        end
    end
    if openGameOver then
        Dispatcher:dispatch(EventType.TinyGameOver_Open);
    end
    return true;
end

function TinyGame:drawLink()
    for i = 1, #self.drawLinkItemDic - 1 do
        local one = self.drawLinkItemDic[i];
        local two = self.drawLinkItemDic[i + 1];
        local length = (math.abs(one.xIndex - two.xIndex) + math.abs(one.yIndex - two.yIndex)) * TinyGameData.distance;
        if i ~= (#self.drawLinkItemDic - 1) then
            length = length + 3;
        end
        local time = length / (TinyGameData.distance * 8);
        local delay = 0;
        if i > 1 then
            delay = self.lineDic[i - 1].delay + self.lineDic[i - 1].time;
        end
        local rotate = 0;
        if (one.yIndex - two.yIndex) < 0 then
            rotate = 0;
        elseif (one.yIndex - two.yIndex) > 0 then
            rotate = 180;
        elseif (one.xIndex - two.xIndex) < 0 then
            rotate = -90;
        elseif (one.xIndex - two.xIndex) > 0 then
            rotate = 90;
        end
        self.lineDic[i]:drawLine(one.gameObject.transform.position, length, time, delay, rotate, function()
            if i == (#self.drawLinkItemDic - 1) then
                self:drawLinkOver();
            end
        end);
    end
end

function TinyGame:drawLinkOver()
    self.drawLinkItemDic = {};
    self.itemSelectedDic[1]:setEmpty(true);
    self.itemSelectedDic[2]:setEmpty(true);
    self.itemSelectedDic = {};
    for i, v in ipairs(self.lineDic) do
        v:setVisible(false);
    end
    self:checkGameOver(true);
end

function TinyGame:autoFinishGame()
    local tempItems = {};
    local keyDic = {};
    for k, v in pairs(self.items) do
        if not v.isEmpty then
            local key = v.xIndex .. "" .. v.yIndex;
            table.insert(keyDic, key);
            tempItems[key] = v;
        end
    end
    for i = 1, #keyDic do
        for k, v in pairs(tempItems) do
            local item = self.items[keyDic[i]];
            if item ~= v and self:isCheckLinked(item, v) then
                item.isEmpty = true;
                v.isEmpty = true;
                self:autoFinishGame();
                return;
            end
        end
    end
    if not self:checkGameOver(false) then
        Utils.log("完成不了！！！！！");
        Utils.log("重新生成了一次游戏！！！！！");
        self:initCheckerboard();
    else
        for _, v in pairs(self.items) do
            local i = v.xIndex;
            local j = v.yIndex;
            if i ~= 0 and j ~= 0 and i ~= (TinyGameData.horizontalCount - 1) and j ~= (TinyGameData.verticalCount - 1) then
                v.isEmpty = false;
            else
                v.isEmpty = true;
            end
        end
    end
end

return ClassUtils:extends(TinyGame, Panel);